/*
	i8259a.c
	
	8259A interrupt controller control code
	
	Meng Sun(c) leon.meng.sun@gmail.com
	Source code released under LGPLv3
	https://www.gnu.org/licenses/lgpl-3.0.txt
*/


#include "i8259a.h"

static callback void (*i8250ISRCallback)(void) = 0x00000000;

static callback void (*i8254ISRCallback)(void) = 0x00000000;

static void callback i8259aInterruptService(void){

	reg8b i8259aIVByte = 0x00;
	
	MASTER_OCW3 = 0x0c; /*send poll command to 8259a*/
	i8259aIVByte = MASTER_OCW3; /*read interrupt status from next nRD pulse*/

	if (i8259aIVByte == 0x80){ /*i8254 timer*/
		i8254ISRCallback();
	} else if (i8259aIVByte == 0x84){ /*i8250 uart*/
		i8250ISRCallback();
	} else {
		/*do nothing*/
	}
	
	return;
}

void i8259aInit(void){
	MASTER_ICW1 = 0x11;
	MASTER_ICW2 = 0x00;
	MASTER_ICW3 = 0x04;
	MASTER_ICW4 = 0x03;
	MASTER_OCW1 = 0xee;
	MASTER_OCW3 = 0x48;
	SLAVE_ICW1 = 0x11;
	SLAVE_ICW2 = 0x10;
	SLAVE_ICW3 = 0x02;
	SLAVE_ICW4 = 0x03;
	SLAVE_OCW1 = 0xff;
	SLAVE_OCW3 = 0x48;
	
	seti8259aISRCallback(&i8259aInterruptService);

	return;
}

void seti8250ISRCallback(void callback (*funcptr)(void)){

	i8250ISRCallback = funcptr;
	return;
}

void seti8254ISRCallback(void callback (*funcptr)(void)){

	i8254ISRCallback = funcptr;
	return;
}

